#include "mf_uart.h"

/**
 * @brief  mf_uart0_init
 * @param  baud_rate
 * @retval FL_ErrorStatus
 */
FL_ErrorStatus mf_uart0_init(const uint32_t baud_rate)
{
    FL_ErrorStatus ret = FL_PASS;
    FL_GPIO_InitTypeDef GPIO_InitStruct;
    FL_UART_InitTypeDef UART0_InitStruct;

    /* PA13 UART0_RX */
    GPIO_InitStruct.pin = FL_GPIO_PIN_13;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_ENABLE;
    GPIO_InitStruct.remapPin = FL_DISABLE;
    ret |= FL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* PA14 UART0_TX */
    GPIO_InitStruct.pin = FL_GPIO_PIN_14;
    GPIO_InitStruct.mode = FL_GPIO_MODE_DIGITAL;
    GPIO_InitStruct.outputType = FL_GPIO_OUTPUT_PUSHPULL;
    GPIO_InitStruct.pull = FL_ENABLE;
    GPIO_InitStruct.remapPin = FL_DISABLE;
    ret |= FL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Init UART0 Struct */
    UART0_InitStruct.clockSrc = FL_RCC_UART0_CLK_SOURCE_APB1CLK;
    UART0_InitStruct.baudRate = baud_rate;
    UART0_InitStruct.dataWidth = FL_UART_DATA_WIDTH_8B;
    UART0_InitStruct.stopBits = FL_UART_STOP_BIT_WIDTH_1B;
    UART0_InitStruct.parity = FL_UART_PARITY_EVEN;
    UART0_InitStruct.transferDirection = FL_UART_DIRECTION_TX_RX;
    ret |= FL_UART_Init(UART0, &UART0_InitStruct);

    return ret;
}

/**
 * @brief  mf_uart_dma_init
 * @param  void
 * @retval FL_ErrorStatus
 * @note
 */
FL_ErrorStatus mf_uart_dma_init(void)
{
    FL_DMA_InitTypeDef DMA_InitStruct;

    DMA_InitStruct.periphAddress = MF_UART0_DMA_PERIPH_ADDRESS; /* [channel_2][Func_2]->reference:fm33le0xx_fl_dma.h */
    DMA_InitStruct.direction = FL_DMA_DIR_RAM_TO_PERIPHERAL;
    DMA_InitStruct.memoryAddressIncMode = FL_DMA_MEMORY_INC_MODE_INCREASE;
    DMA_InitStruct.flashAddressIncMode = FL_DMA_CH7_FLASH_INC_MODE_INCREASE;
    DMA_InitStruct.dataSize = FL_DMA_BANDWIDTH_8B;
    DMA_InitStruct.priority = FL_DMA_PRIORITY_LOW;
    DMA_InitStruct.circMode = FL_DISABLE;

    return FL_DMA_Init(DMA, &DMA_InitStruct, MF_UART0_DMA_CHANNEL);
}

/**
 * @brief uart0_dma_data_addr
 * @param *data_param
 * @return FL_ErrorStatus
 */
static FL_ErrorStatus uart0_dma_data_addr(uint8_t *data_param)
{
    FL_DMA_ConfigTypeDef DMA_ConfigStruct = {0};

    DMA_ConfigStruct.memoryAddress = (uint32_t)data_param;                                       /* set str base_address */
    DMA_ConfigStruct.transmissionCount = strlen((const char *)data_param) - 1;                   /* set dma request_num */
    return FL_DMA_StartTransmission(MF_UART0_DMA_BASE, &DMA_ConfigStruct, MF_UART0_DMA_CHANNEL); /* start request_num */
}

/**
 * @brief uart0_dma_send_str
 * @param *data_param
 * @return None
 */
void uart0_dma_send_str(uint8_t *data_param)
{
    FL_DMA_Enable(MF_UART0_DMA_BASE); /* enable dma */
    uart0_dma_data_addr(data_param);  /* set dma data */
    FL_UART_EnableTX(MF_UART0_BASE);  /* enable uart0 tx */
}

/**
 * @brief uart0_send_byte
 * @param data_param
 * @return None
 */
void uart0_send_byte(const char data_param)
{
    FL_UART_WriteTXBuff(MF_UART0_BASE, data_param);
    while (!FL_UART_IsActiveFlag_TXBuffEmpty(MF_UART0_BASE))
        ;
}

/**
 * @brief uart0_send_str
 * @param *data_param
 * @return None
 */
void uart0_send_str(const char *data_param)
{
    uint8_t str_buf_length = strlen(data_param);
    for (uint8_t i = 0; i < str_buf_length; i++)
    {
        FL_UART_WriteTXBuff(MF_UART0_BASE, data_param[i]);
        while (!FL_UART_IsActiveFlag_TXBuffEmpty(MF_UART0_BASE))
            ;
    }
}

/**
 * @brief uart0_dma_printf
 * @param *format
 * @return None
 */
void uart0_dma_printf(const char *tag, const char *format, ...)
{
    char buffer[256];
    va_list args;

    va_start(args, format);
    snprintf(buffer, sizeof(buffer), "[%s] ", tag);
    vsnprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), format, args);
    uart0_dma_send_str((uint8_t *)buffer);
    va_end(args);
}